#include "Compensation.h"

#define COMPENSATION_FLASH_DATA_SIZE 5 /* Flash中的补偿系数数据大小 */
#define FLAG_POS                     4 /* 标志位的位置 */

/* 私有函数声明 */
static int     Compensation_ReadFlashData(uint8_t *flashData);
static void    Compensation_SetDefaultValues(void);
static int     Compensation_ValidateFlashData(const uint8_t *flashData);
static uint8_t Compensation_GetCurrentChannel(void);
static int     Compensation_IsValueValid(uint32_t value);
static int     Compensation_HandleNewInitialValue(void);
static int     Compensation_HandleZeroPressure(void);
static int     Compensation_CalculateCoefficient(void);
static int     Compensation_WriteFlashData(const uint8_t *data);
static uint8_t Compensation_GetNodeID(void);
static uint8_t Compensation_NodeID2ChannelIndex(uint8_t nodeId);
static int     Compensation_HandleErasureFlash(void);

extern sensor_point_info_t sensor_info;

/**
 * @brief 温湿度补偿初始化
 */
void Compensation_Init(void)
{
    uint8_t flashData[COMPENSATION_FLASH_DATA_SIZE] = { 0 };

    /* 读取Flash数据并验证 */
    if (Compensation_ReadFlashData(flashData) != 0) {
        /* Flash读取失败，使用默认值 */
        Compensation_SetDefaultValues();
        return;
    }

    /* 验证数据有效性 */
    if (Compensation_ValidateFlashData(flashData) != 0) {
        Compensation_SetDefaultValues();
        return;
    }

    /* 解析数据 */
    compensation.initialValue = flashData[0] | (flashData[1] << 8);
    // uint16_t tmpCoefficient   = flashData[2] | (flashData[3] << 8);
    compensation.coefficient  = 1.0f /*  * tmpCoefficient / 1000 */;
    is_comp_en                = true;
}

/**
 * @brief 温湿度补偿回调
 */
void Compensation_Callback(void)
{
    /* 获取当前点位信息 */
    uint8_t channelPos = Compensation_GetCurrentChannel();
    if (channelPos == 0) return;

    /* 获取当前值 */
    uint32_t currentValue = (uint32_t)(res_data_arr[channelPos].Res_value);
    // LOG("Current Value: %d\n", currentValue);

    /* 验证当前值有效性 */
    if (!Compensation_IsValueValid(currentValue)) return;

    // LOG("Data vaild\n");

    compensation.currentValue = currentValue;

    /* 处理补偿逻辑 */
    if (is_recv_comp_init_val) {
        Compensation_HandleNewInitialValue();
    }
    else if (is_recv_erasure_flash) {
        Compensation_HandleErasureFlash();
    }
    else if (is_comp_en) {
        Compensation_HandleZeroPressure();
        // LOG("HandleZeroPressure\n");
    }

    /* 打印系数 */
    // LOG("init: %d\n", compensation.initialValue);
    // LOG("current: %d\n", compensation.currentValue);
    // LOG("coefficient: 0.%d\n", (int)(compensation.coefficient * 1000));
}

/**
 * @brief 从Flash读取数据
 * @param flashData 数据缓冲区
 * @return 0:成功 其他:失败
 */
static int Compensation_ReadFlashData(uint8_t *flashData)
{
    if (flashData == NULL) return -1;

    return VME2P_Read(VM_INDEX_COMPENSATION, flashData, COMPENSATION_FLASH_DATA_SIZE) !=
           COMPENSATION_FLASH_DATA_SIZE;
}

/**
 * @brief 设置默认值
 */
static void Compensation_SetDefaultValues(void)
{
    compensation.initialValue = 1;
    compensation.currentValue = 1;
    compensation.coefficient  = 1.0f;
    is_comp_en                = false;
}

/**
 * @brief 验证Flash数据有效性
 * @return 0:有效 其他:无效
 */
static int Compensation_ValidateFlashData(const uint8_t *flashData)
{
    if (flashData == NULL) return -1;

    /* 验证标志位 */
    if (flashData[FLAG_POS] != FLASH_WRITE_FLAG) return -1;

    /* 验证初始值和系数范围 */
    uint16_t initialValue = flashData[0] | (flashData[1] << 8);
    // uint16_t coefficient  = flashData[2] | (flashData[3] << 8);

    if (initialValue < 100 || initialValue > MAX_VALID_VALUE /*  || coefficient == 0 */) return -1;

    return 0;
}

/**
 * @brief 获取当前补偿点的通道
 * @return 通道索引，0表示无效
 */
static uint8_t Compensation_GetCurrentChannel(void)
{
    uint8_t nodeId = Compensation_GetNodeID();
    if (nodeId == 0) return 0;

    return Compensation_NodeID2ChannelIndex(nodeId);
}

/**
 * @brief 验证值是否有效
 * @param value 待验证的值
 * @return 0:无效 1:有效
 */
static int Compensation_IsValueValid(uint32_t value)
{
    return (value > MIN_VALID_VALUE && value <= MAX_VALID_VALUE);
}

/**
 * @brief 处理新的初始值
 * @return 0:成功 其他:失败
 */
static int Compensation_HandleNewInitialValue(void)
{
    is_recv_comp_init_val = false;
    is_comp_en            = true;

    /* 计算新系数 */
    if (Compensation_CalculateCoefficient() != 0) return -1;

    /* 准备Flash数据 */
    uint8_t writeData[COMPENSATION_FLASH_DATA_SIZE] = { 0 };
    writeData[0]                                    = compensation.initialValue & 0xFF;
    writeData[1]                                    = (compensation.initialValue >> 8) & 0xFF;

    // uint16_t tmpCoefficient = (uint16_t)(compensation.coefficient * 1000);
    // writeData[2]            = tmpCoefficient & 0xFF;
    // writeData[3]            = (tmpCoefficient >> 8) & 0xFF;
    writeData[FLAG_POS] = FLASH_WRITE_FLAG;

    /* 写入Flash */
    return Compensation_WriteFlashData(writeData);
}

/**
 * @brief 处理零压力情况
 * @return 0:成功 其他:失败
 */
static int Compensation_HandleZeroPressure(void)
{
    // uint8_t flashData[COMPENSATION_FLASH_DATA_SIZE] = { 0 };

    /* 读取并验证Flash数据 */
    // if (Compensation_ReadFlashData(flashData) != 0 || Compensation_ValidateFlashData(flashData) != 0)
    //     return -1;

    /* 计算新系数 */
    if (Compensation_CalculateCoefficient() != 0) return -1;

    /* 更新系数 */
    // uint16_t tmpCoefficient = (uint16_t)(compensation.coefficient * 1000);
    // flashData[2]            = tmpCoefficient & 0xFF;
    // flashData[3]            = (tmpCoefficient >> 8) & 0xFF;

    /* 写入Flash */
    return 0;
}

/**
 * @brief 计算补偿系数并验证
 * @return 0:成功 其他:失败
 */
static int Compensation_CalculateCoefficient(void)
{
    if (compensation.currentValue == 0) return -1;

    float newCoefficient = 1.0f * compensation.initialValue / compensation.currentValue;

    /* 验证系数是否在合理范围内 */
    if (newCoefficient <= 0) return -1;

    compensation.coefficient = newCoefficient;
    return 0;
}

/**
 * @brief 写入Flash数据
 * @param data 待写入的数据
 * @return 0:成功 其他:失败
 */
static int Compensation_WriteFlashData(const uint8_t *data)
{
    if (data == NULL) return -1;

    return VME2P_Write(VM_INDEX_COMPENSATION, data, COMPENSATION_FLASH_DATA_SIZE) !=
           COMPENSATION_FLASH_DATA_SIZE;
}

/**
 * @brief 获取NodeID
 * @return 成功返回id, 失败返回0
 */
static uint8_t Compensation_GetNodeID(void)
{
    uint8_t nodeId = 0;
    if (Dev_ReadNodeID(&nodeId) == 0) return 0;
    return nodeId;
}

/**
 * @brief 根据NodeID转换为通道索引
 * @param nodeId NodeID
 * @return ADC通道索引，0表示无效
 */
static uint8_t Compensation_NodeID2ChannelIndex(uint8_t nodeId)
{
    if (sensor_info.comp_config.is_config) {
        return sensor_info.comp_config.comp_point_arr[0];
    }

    uint8_t channelIndex = 0;
    switch (nodeId) {
    case NODE_ID_LK1A_LEG:    channelIndex = COMP_POINT_LK1A_LEG_L; break;
    case NODE_ID_LK1A_LUMBAR: channelIndex = COMP_POINT_LK1A_LUMBAR; break;
    case NODE_ID_LK1A_RIGHT:  channelIndex = COMP_POINT_LK1A_RIGHT; break;
    case NODE_ID_LK1A_LEFT:   channelIndex = COMP_POINT_LK1A_LEFT; break;
    case NODE_ID_PK1B_BACK:   channelIndex = COMP_POINT_PK1B_BACK; break;
    case NODE_ID_PK1B_LEG:    channelIndex = COMP_POINT_PK1B_LEG_L; break;
    case NODE_ID_PK1B_LUMBAR: channelIndex = COMP_POINT_PK1B_LUMBAR; break;
    case NODE_ID_PK1B_RIGHT:  channelIndex = COMP_POINT_PK1B_RIGHT; break;
    case NODE_ID_PK1B_LEFT:   channelIndex = COMP_POINT_PK1B_LEFT; break;
    }
    return channelIndex;
}

/**
 * @brief 处理擦除Flash中系数的操作
 *
 * @return int 0:成功 其他:失败
 */
static int Compensation_HandleErasureFlash(void)
{
    is_recv_erasure_flash = false;
    is_comp_en            = false;

    /* 所有值都变为1 */
    uint8_t flashData[COMPENSATION_FLASH_DATA_SIZE] = { 1, 1, 1, 1, 1 };

    /* 更新当前系数为1 */
    compensation.coefficient = 1.0f;

    /* 覆盖原有系数 */
    return VME2P_Write(VM_INDEX_COMPENSATION, flashData, COMPENSATION_FLASH_DATA_SIZE) !=
           COMPENSATION_FLASH_DATA_SIZE;
}
